package com.qst.order.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.rabbitmq.client.Channel;

import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.AMQP; // 新增：RabbitMQ声明返回类所在包
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.sql.DataSource;
import java.io.IOException;
import java.net.InetAddress;
import java.sql.ResultSet; // 新增：SQL结果集导入
import java.sql.Statement;
import java.util.*;
import java.util.stream.Collectors;
import java.lang.management.*;

/**
 * 单体架构下的系统监控服务（适配调整后的Maven依赖）
 */
@Slf4j
@Service
public class SystemMonitorService {
    // 注入当前项目依赖的核心Bean
    @Autowired
    private RedisTemplate<String, Object> redisTemplate; // 替换原JedisPool（Spring Data Redis）
    @Autowired
    private DataSource dataSource;
    @Autowired
    private JdbcTemplate jdbcTemplate; // 用于操作MySQL存储时序数据
    @Value("${server.port}") // 从配置文件读取当前应用端口（避免硬编码）
    private Integer serverPort;


    @Value("${spring.rabbitmq.addresses}")
    private String rabbitAddresses;

    @Value("${spring.rabbitmq.username}")
    private String rabbitUsername;

    @Value("${spring.rabbitmq.password}")
    private String rabbitPassword;

    @Value("${spring.rabbitmq.virtual-host}")
    private String rabbitVhost;



    /**
     * 聚合获取所有监控数据（适配单体架构）
     */
    public SystemMonitorDTO getSystemMonitorData() {
        SystemMonitorDTO result = new SystemMonitorDTO();
        // 1. 采集各模块数据（均适配单体架构）
        result.setOverview(getSystemOverview());
        result.setServiceInstances(getServiceInstances()); // 单体：仅当前应用实例
        result.setRabbitMQQueues(getRabbitMQQueues());
        result.setRedisStatus(getRedisStatus()); // 适配Spring Data Redis
        result.setMysqlStatus(getMysqlStatus());
        result.setResponseTimeTrend(getResponseTimeTrend()); // 改用MySQL存储
        return result;
    }


    // ------------------------------ 1. 系统概览数据采集 ------------------------------
    private SystemOverviewDTO getSystemOverview() {
        SystemOverviewDTO overview = new SystemOverviewDTO();
        // 系统状态：检查核心组件（MySQL+Redis）可用性
        boolean mysqlAlive = isMysqlAlive();
        boolean redisAlive = isRedisAlive();
        overview.setSystemStatus((mysqlAlive && redisAlive) ? "UP" : "DOWN");
        // 最后检查时间
        overview.setLastCheckTime(DateUtil.now());
        // 服务实例数：单体架构固定为1
        overview.setServiceInstanceCount(1);
        // 平均响应时间：从MySQL时序表获取（非模拟）
        overview.setAvgResponseTime(getRecentAvgResponseTime());
        // 错误率：模拟（实际可从日志统计，如Feign调用错误率）
        overview.setErrorRate(NumberUtil.round(Math.random() * 5, 1).doubleValue());
        return overview;
    }

    // 检查MySQL可用性
    private boolean isMysqlAlive() {
        try (java.sql.Connection conn = dataSource.getConnection()) {
            return conn.isValid(3000); // 3秒超时校验
        } catch (Exception e) {
            log.error("MySQL连接失败", e);
            return false;
        }
    }

    // 检查Redis可用性（优化泛型）
    private boolean isRedisAlive() {
        try {
            // 通过执行PING命令校验Redis连接（简化泛型声明）
            return Boolean.TRUE.equals(redisTemplate.execute((RedisCallback<Boolean>) session -> {
                session.ping();
                return Boolean.TRUE;
            }));
        } catch (Exception e) {
            log.error("Redis连接失败", e);
            return false;
        }
    }
    /**
     * 清空RabbitMQ队列（供前端调用）
     */
    public void purgeQueue(String queueName) throws Exception {
        try (com.rabbitmq.client.Connection conn = getRabbitConnection();
             Channel channel = conn.createChannel()) {
            // 执行清空队列操作
            channel.queuePurge(queueName);
            log.info("队列 {} 已清空", queueName);
        } catch (Exception e) {
            log.error("清空队列 {} 失败", queueName, e);
            throw new RuntimeException("清空队列失败");
        }
    }


    // ------------------------------ 2. 服务实例数据采集（修复Hutool语法） ------------------------------
    private List<ServiceInstanceDTO> getServiceInstances() {
        List<ServiceInstanceDTO> instances = new ArrayList<>();
        ServiceInstanceDTO currentInstance = new ServiceInstanceDTO();

        try {
            // 1. 基础信息（单体应用固定值）
            currentInstance.setInstanceId("single-app-" + InetAddress.getLocalHost().getHostAddress());
            currentInstance.setServiceId("order-project"); // 与pom.xml的artifactId一致
            currentInstance.setHost(InetAddress.getLocalHost().getHostAddress()); // 当前服务器IP
            currentInstance.setPort(serverPort); // 从配置文件注入的应用端口
            currentInstance.setStatus("UP"); // 单体应用运行状态

            // 2. 运行时间（修复Hutool格式化：直接使用格式字符串）
            RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
            long uptimeMs = runtimeBean.getUptime();
            // 正确用法：第二个参数直接传格式字符串（d=天, H=小时, m=分钟）
            // 枚举常量对应“d天H小时m分钟”格式，无需手动写字符串
            // 手动拆分“天、小时、分钟”
            long days = uptimeMs / (24 * 60 * 60 * 1000);
            long hours = (uptimeMs % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000);
            long minutes = (uptimeMs % (60 * 60 * 1000)) / (60 * 1000);
            String uptimeStr = days + "天" + hours + "小时" + minutes + "分钟";
            currentInstance.setUptime(uptimeStr);
            // 3. CPU使用率（兼容处理：使用扩展类获取，避免方法不存在错误）
            int cpuUsage = -1; // 默认为-1表示获取失败
            // 强制转换为Sun JDK扩展类（支持getSystemCpuLoad()方法）
            if (ManagementFactory.getOperatingSystemMXBean() instanceof com.sun.management.OperatingSystemMXBean) {
                com.sun.management.OperatingSystemMXBean osBean =
                        (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
                // 获取系统CPU使用率（0.0~1.0），转换为百分比
                double systemCpuLoad = osBean.getSystemCpuLoad();
                if (systemCpuLoad >= 0) { // 确保值有效
                    cpuUsage = (int) (systemCpuLoad * 100);
                    cpuUsage = Math.min(cpuUsage, 100); // 避免超过100%
                }
            }
            currentInstance.setCpuUsage(cpuUsage);

            // 4. 内存使用率（JVM堆内存：已用/最大）
            MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
            MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
            long usedMemory = heapUsage.getUsed() / (1024 * 1024); // 转MB
            long maxMemory = heapUsage.getMax() / (1024 * 1024);
            int memoryUsage = maxMemory > 0 ? (int) (usedMemory * 100.0 / maxMemory) : 0;
            currentInstance.setMemoryUsage(memoryUsage);

        } catch (Exception e) {
            log.error("获取当前应用状态失败", e);
            currentInstance.setStatus("ERROR"); // 标记异常状态
        }

        instances.add(currentInstance);
        return instances;
    }



    // ------------------------------ 3. RabbitMQ队列数据采集（修复API版本问题） ------------------------------
    private List<RabbitMQQueueDTO> getRabbitMQQueues() {
        List<RabbitMQQueueDTO> queues = new ArrayList<>();
        // RabbitMQ管理API地址（默认端口15672，与AMQP端口5672不同）
        String managementApiUrl = "http://192.168.10.132:15672/api/queues";

        try {
            // 1. 通过管理API获取所有队列的基本信息（名称、vhost等）
            RestTemplate restTemplate = new RestTemplate();
            // 设置管理API的认证信息（与AMQP的用户名密码相同）
            restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(rabbitUsername, rabbitPassword));

            // 调用API获取队列列表（返回JSON数组）
            JsonNode allQueues = restTemplate.getForObject(managementApiUrl, JsonNode.class);

            // 2. 遍历所有队列，获取详细状态
            try (com.rabbitmq.client.Connection conn = getRabbitConnection();
                 Channel channel = conn.createChannel()) {

                for (JsonNode queueNode : allQueues) {
                    String queueName = queueNode.get("name").asText();
                    String vhost = queueNode.get("vhost").asText();

                    // 只处理当前vhost下的队列（与配置一致）
                    if (!vhost.equals(rabbitVhost)) {
                        continue;
                    }

                    RabbitMQQueueDTO dto = new RabbitMQQueueDTO();
                    dto.setName(queueName);

                    try {
                        // 获取队列详细状态（消息数、消费者数）
                        AMQP.Queue.DeclareOk declareOk = channel.queueDeclarePassive(queueName);
                        dto.setMessageCount((long) declareOk.getMessageCount());
                        dto.setConsumerCount(declareOk.getConsumerCount());
                        dto.setStatus("ACTIVE");
                        dto.setMemoryUsage((int) (Math.random() * 190 + 10) + " MB"); // 模拟内存占用
                    } catch (IOException e) {
                        // 极少数情况：API返回存在但实际查询失败（如队列被删除）
                        dto.setStatus("INACTIVE");
                        dto.setMessageCount(0L);
                        dto.setConsumerCount(0);
                    }

                    queues.add(dto);
                }
            }

        } catch (Exception e) {
            log.error("获取RabbitMQ队列信息失败: {}", e.getMessage(), e);
            // 异常时返回空列表或错误标记
            RabbitMQQueueDTO errorDto = new RabbitMQQueueDTO();
            errorDto.setName("获取失败");
            errorDto.setStatus("ERROR");
            queues.add(errorDto);
        }

        return queues;
    }


    // 创建RabbitMQ连接
    // 创建RabbitMQ连接（适配集群）
    public Connection getRabbitConnection() throws Exception {
        try {
            // 正确处理虚拟主机路径
            String vhost = rabbitVhost;
            if (vhost.equals("/")) {
                vhost = "%2F"; // URL编码根虚拟主机
            } else if (vhost.startsWith("/")) {
                vhost = vhost.substring(1); // 移除前导斜杠
            }

            // 对于集群地址，只取第一个地址构建URI
            String[] addressArray = rabbitAddresses.split(",");
            String firstAddress = addressArray[0].trim();
            String host = firstAddress;
            int port = 5672;

            if (firstAddress.contains(":")) {
                String[] parts = firstAddress.split(":");
                host = parts[0];
                port = Integer.parseInt(parts[1]);
            }

            String amqpUri = String.format(
                    "amqp://%s:%s@%s:%d/%s",
                    rabbitUsername, rabbitPassword, host, port, vhost
            );

            //log.info("构建的AMQP URI: {}", amqpUri);

            ConnectionFactory factory = new ConnectionFactory();
            factory.setUri(amqpUri);
            return factory.newConnection();

        } catch (Exception e) {
            log.error("连接RabbitMQ失败: {}", e.getMessage(), e);
            throw new RuntimeException("无法连接到RabbitMQ: " + e.getMessage(), e);
        }
    }

    // ------------------------------ 4. Redis状态数据采集 ------------------------------
    private RedisStatusDTO getRedisStatus() {
        RedisStatusDTO redisStatus = new RedisStatusDTO();

        try {
            // 执行Redis的INFO命令，获取Properties类型的结果（替代弃用的String转换）
            Properties redisInfoProps = redisTemplate.execute((RedisCallback<Properties>) connection -> connection.info());

            // 将Properties转换为Map<String, String>，方便后续解析
            Map<String, String> infoMap = new HashMap<>();
            redisInfoProps.forEach((key, value) -> {
                if (key != null && value != null) {
                    infoMap.put(key.toString(), value.toString());
                }
            });

            // 填充Redis状态字段
            redisStatus.setServerVersion(infoMap.getOrDefault("redis_version", "未知"));
            redisStatus.setMode(infoMap.getOrDefault("redis_mode", "unknown"));
            // 已用内存（转MB：info返回的是字节数）
            long usedMemory = Long.parseLong(infoMap.getOrDefault("used_memory", "0")) / (1024 * 1024);
            redisStatus.setUsedMemory(usedMemory + " MB");
            // 内存使用率（模拟：实际需结合maxmemory计算）
            redisStatus.setMemoryUsage(NumberUtil.round(Math.random() * 50 + 30, 1).doubleValue());
            // 连接数、键总数
            redisStatus.setConnectedClients(Integer.parseInt(infoMap.getOrDefault("connected_clients", "0")));
            redisStatus.setDbKeys(getRedisTotalKeys(infoMap));
            // 命中率（keyspace_hits / (hits + misses)）
            long hits = Long.parseLong(infoMap.getOrDefault("keyspace_hits", "0"));
            long misses = Long.parseLong(infoMap.getOrDefault("keyspace_misses", "0"));
            double hitRate = (hits + misses) == 0 ? 100 : NumberUtil.round((double) hits / (hits + misses) * 100, 1).doubleValue();
            redisStatus.setHitRate(hitRate);
        } catch (Exception e) {
            log.error("获取Redis状态失败", e);
            redisStatus.setStatus("error");
        }
        return redisStatus;
    }

    // 解析Redis INFO命令结果
    private Map<String, String> parseRedisInfo(String info) {
        Map<String, String> infoMap = new HashMap<>();
        for (String line : info.split("\n")) {
            if (line.startsWith("#") || line.isEmpty() || !line.contains(":")) {
                continue;
            }
            String[] parts = line.split(":", 2); // 避免值包含":"的情况
            infoMap.put(parts[0].trim(), parts[1].trim());
        }
        return infoMap;
    }

    // 计算Redis所有DB的键总数（从INFO解析，无需切换DB）
    private long getRedisTotalKeys(Map<String, String> infoMap) {
        long totalKeys = 0;
        // INFO中db开头的字段格式：db0:keys=100,expires=10
        for (Map.Entry<String, String> entry : infoMap.entrySet()) {
            String key = entry.getKey();
            if (key.startsWith("db")) {
                String value = entry.getValue();
                String[] kvPairs = value.split(",");
                for (String kv : kvPairs) {
                    if (kv.startsWith("keys=")) {
                        totalKeys += Long.parseLong(kv.split("=")[1]);
                        break;
                    }
                }
            }
        }
        return totalKeys;
    }


    // ------------------------------ 5. MySQL状态数据采集（修复ResultSet导入） ------------------------------
    private MysqlStatusDTO getMysqlStatus() {
        MysqlStatusDTO mysqlStatus = new MysqlStatusDTO();

        try (java.sql.Connection conn = dataSource.getConnection();
             Statement stmt = conn.createStatement()) {

            // 1. 数据库版本
            ResultSet rsVersion = stmt.executeQuery("SELECT VERSION() AS version");
            if (rsVersion.next()) {
                mysqlStatus.setServerVersion(rsVersion.getString("version"));
            }

            // 2. 运行时间（修复：使用格式字符串替代错误的枚举值）
            ResultSet rsUptime = stmt.executeQuery("SHOW STATUS LIKE 'Uptime'");
            if (rsUptime.next()) {
                long uptimeSec = Long.parseLong(rsUptime.getString("Value"));
                // 正确用法：直接传递格式字符串 "d天H小时"
                // 先将“秒”转为“毫秒”，再拆分“天、小时”
                long mysqlUptimeMs = uptimeSec * 1000;
                long daysMysql = mysqlUptimeMs / (24 * 60 * 60 * 1000);
                long hoursMysql = (mysqlUptimeMs % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000);
                String mysqlUptimeStr = daysMysql + "天" + hoursMysql + "小时";
                mysqlStatus.setUptime(mysqlUptimeStr);
            }

            // 3. 当前连接数
            ResultSet rsConn = stmt.executeQuery("SHOW STATUS LIKE 'Threads_connected'");
            if (rsConn.next()) {
                mysqlStatus.setConnections(Integer.parseInt(rsConn.getString("Value")));
            }

            // 4. QPS（Questions / 运行时间）
            long questions = Long.parseLong(getMysqlStatusValue(stmt, "Questions"));
            long uptimeSecQps = Long.parseLong(getMysqlStatusValue(stmt, "Uptime")); // 重命名避免变量重复
            mysqlStatus.setQps(uptimeSecQps == 0 ? 0 : (int) (questions / uptimeSecQps));

            // 5. TPS（(Com_commit + Com_rollback) / 运行时间）
            long commit = Long.parseLong(getMysqlStatusValue(stmt, "Com_commit"));
            long rollback = Long.parseLong(getMysqlStatusValue(stmt, "Com_rollback"));
            mysqlStatus.setTps(uptimeSecQps == 0 ? 0 : (int) ((commit + rollback) / uptimeSecQps));

            // 6. 缓存命中率（模拟，NumberUtil 方法有效）
            mysqlStatus.setTableCacheHitRate(NumberUtil.round(Math.random() * 9 + 90, 0).doubleValue());
            mysqlStatus.setInnodbBufferPoolHitRate(NumberUtil.round(Math.random() * 4.9 + 95, 1).doubleValue());
        } catch (Exception e) {
            log.error("获取MySQL状态失败", e);
            mysqlStatus.setStatus("error");
        }
        return mysqlStatus;
    }

    // 辅助：获取MySQL状态值
    private String getMysqlStatusValue(Statement stmt, String variable) throws Exception {
        // 白名单：仅允许已知的状态变量
        Set<String> allowedVariables = new HashSet<>(Arrays.asList(
                "Questions", "Uptime", "Com_commit", "Com_rollback", "Threads_connected"
        ));
        if (!allowedVariables.contains(variable)) {
            throw new IllegalArgumentException("不支持的状态变量：" + variable);
        }
        // 拼接时对变量中的单引号转义（进一步加固）
        String safeVariable = variable.replace("'", "''");
        ResultSet rs = stmt.executeQuery("SHOW STATUS LIKE '" + safeVariable + "'");
        try { // 显式关闭ResultSet
            return rs.next() ? rs.getString("Value") : "0";
        } finally {
            rs.close();
        }
    }


    // ------------------------------ 6. 响应时间趋势 ------------------------------
    private ResponseTimeTrendDTO getResponseTimeTrend() {
        ResponseTimeTrendDTO trend = new ResponseTimeTrendDTO();
        List<String> timestamps = new ArrayList<>();
        List<Long> avgList = new ArrayList<>();
        List<Long> maxList = new ArrayList<>();

        try {
            // 1. 从原始表查询过去30分钟的数据，按分钟分组计算平均和最大响应时间
            String sql = "SELECT " +
                    "DATE_FORMAT(request_time, '%H:%i') AS time_str, " +  // 按“时:分”格式化时间
                    "ROUND(AVG(response_time)) AS avg_response_time, " +  // 平均响应时间（四舍五入）
                    "MAX(response_time) AS max_response_time " +         // 最大响应时间
                    "FROM api_response_time_raw " +                      // 原始数据表
                    "WHERE request_time >= DATE_SUB(NOW(), INTERVAL 30 MINUTE) " + // 筛选过去30分钟
                    "GROUP BY time_str " +                               // 按分钟分组
                    "ORDER BY time_str ASC";                             // 按时间升序排列

            // 2. 执行查询，用Map存储结果（key:时间字符串，value: avg和max）
            Map<String, Map<String, Long>> resultMap = new HashMap<>();
            jdbcTemplate.query(sql, rs -> {
                String timeStr = rs.getString("time_str");
                Long avg = rs.getLong("avg_response_time");
                Long max = rs.getLong("max_response_time");

                Map<String, Long> data = new HashMap<>();
                data.put("avg", avg);
                data.put("max", max);
                resultMap.put(timeStr, data);
            });

            // 3. 生成过去30分钟的完整时间轴（确保每个分钟都有数据，无数据则补0）
            for (int i = 29; i >= 0; i--) {
                // 计算30分钟内的每个时间点（如当前时间-29分钟、-28分钟...0分钟）
                Date time = DateUtil.offsetMinute(new Date(), -i);
                String timeStr = DateUtil.format(time, "HH:mm");

                // 从查询结果中获取该分钟的数据，无数据则用0
                Map<String, Long> data = resultMap.getOrDefault(timeStr, new HashMap<>());
                Long avg = data.getOrDefault("avg", 0L);
                Long max = data.getOrDefault("max", 0L);

                timestamps.add(timeStr);
                avgList.add(avg);
                maxList.add(max);
            }

        } catch (Exception e) {
            log.error("查询响应时间趋势失败", e);
            // 异常时返回空趋势（前端显示无数据）
            timestamps.add(DateUtil.format(new Date(), "HH:mm"));
            avgList.add(0L);
            maxList.add(0L);
        }

        trend.setTimestamps(timestamps);
        trend.setAvgResponseTimeList(avgList);
        trend.setMaxResponseTimeList(maxList);
        return trend;
    }

    /**
     * 定时保存响应时间数据到MySQL（每分钟执行一次）
     * 注：启动类需加@EnableScheduling开启定时任务
     */@Scheduled(fixedRate = 60000)
    public void saveResponseTimeToMysql() {
        try {
            // 1. 查询过去1分钟的聚合数据
            String sql = "SELECT " +
                    "ROUND(AVG(response_time)) AS avg_time, " +
                    "MAX(response_time) AS max_time " +
                    "FROM api_response_time_raw " +
                    "WHERE request_time >= DATE_SUB(NOW(), INTERVAL 1 MINUTE)";

            Map<String, Object> result = null;
            try {
                result = jdbcTemplate.queryForMap(sql);
            } catch (EmptyResultDataAccessException e) {
                log.debug("过去1分钟内无接口请求数据，跳过存储");
                return;
            }

            // 2. 提取聚合结果（关键修复：先判断null，再处理）
            // 平均响应时间：若为null，默认0
            Long avgTime = result.get("avg_time") != null
                    ? Long.valueOf(result.get("avg_time").toString())
                    : 0L;

            // 最大响应时间：若为null，默认0
            Long maxTime = result.get("max_time") != null
                    ? Long.valueOf(result.get("max_time").toString())
                    : 0L;

            // 3. 插入或更新聚合表（即使为0也正常存储，避免数据断层）
            String timestamp = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:00");
            String insertSql = "INSERT INTO response_time_trend " +
                    "(timestamp, avg_response_time, max_response_time) " +
                    "VALUES (?, ?, ?) " +
                    "ON DUPLICATE KEY UPDATE " +
                    "avg_response_time = VALUES(avg_response_time), " +
                    "max_response_time = VALUES(max_response_time)";

            jdbcTemplate.update(insertSql, timestamp, avgTime, maxTime);
            log.debug("响应时间数据保存成功：{} avg={}ms max={}ms", timestamp, avgTime, maxTime);

        } catch (Exception e) {
            log.error("保存响应时间数据失败", e);
        }
    }
    // 辅助：获取最近5分钟平均响应时间（从MySQL查询）
    private Long getRecentAvgResponseTime() {
        try {
            // SQL：查询最近5分钟内所有请求的平均响应时间（四舍五入为整数毫秒）
            String sql = "SELECT ROUND(AVG(response_time)) AS avg5min " +  // 对平均值四舍五入
                    "FROM api_response_time_raw " +
                    "WHERE request_time >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)";  // 筛选最近5分钟的数据

            // 执行查询：若没有数据，queryForObject会抛异常，由catch块处理
            return jdbcTemplate.queryForObject(sql, Long.class);
        } catch (Exception e) {
            // 异常场景：表中无数据、查询失败等，返回0或模拟值（根据业务需求选择）
            log.error("查询最近5分钟平均响应时间失败", e);
            return 0L; // 建议返回0而非模拟值，更能体现"无数据"状态
        }
    }


    // ------------------------------ 内部DTO类（Lombok Data注解） ------------------------------
    @Data
    public static class SystemMonitorDTO {
        private SystemOverviewDTO overview;
        private List<ServiceInstanceDTO> serviceInstances;
        private List<RabbitMQQueueDTO> rabbitMQQueues;
        private RedisStatusDTO redisStatus;
        private MysqlStatusDTO mysqlStatus;
        private ResponseTimeTrendDTO responseTimeTrend;
    }

    @Data
    public static class SystemOverviewDTO {
        private String systemStatus;
        private String lastCheckTime;
        private Integer serviceInstanceCount;
        private Long avgResponseTime;
        private Double errorRate;
    }

    @Data
    public static class ServiceInstanceDTO {
        private String instanceId;
        private String serviceId;
        private String host;
        private Integer port;
        private String status;
        private String uptime;
        private Integer cpuUsage;
        private Integer memoryUsage;
    }

    @Data
    public static class RabbitMQQueueDTO {
        private String name;
        private Long messageCount;
        private Integer consumerCount;
        private String status;
        private String memoryUsage;
    }

    @Data
    public static class RedisStatusDTO {
        private String serverVersion;
        private String mode;
        private String usedMemory;
        private Double memoryUsage;
        private Integer connectedClients;
        private Long dbKeys;
        private Double hitRate;
        private String status; // 标记Redis是否异常
    }

    @Data
    public static class MysqlStatusDTO {
        private String serverVersion;
        private String uptime;
        private Integer connections;
        private Integer qps;
        private Integer tps;
        private Double tableCacheHitRate;
        private Double innodbBufferPoolHitRate;
        private String status; // 标记MySQL是否异常
    }

    @Data
    public static class ResponseTimeTrendDTO {
        private List<String> timestamps;
        private List<Long> avgResponseTimeList;
        private List<Long> maxResponseTimeList;
    }
}